<template>
  <div class="ls-table table-container">
    <el-table
      ref="lsTable"
      :class="tableClass"
      v-bind="tableProps"
      :data="data"
      v-loading="loading"
      @selection-change="handleSelectionChange"
      @sort-change="sortChange"
      v-on="events || {}"
    >
      <template v-for="(item, index) in config">
        <template v-if="!item.hide && !(item.hidden && item.hidden())">
          <!-- 序号和选择 -->
          <el-table-column
            v-if="['selection', 'index'].includes(item.type)"
            :key="configString + index"
            v-bind="item"
            :index="paging && ((i) => paging.page * paging.size + i + 1 - paging.size)"
            :width="item.width || '55'"
            :align="item.align || 'center'"
          >
          </el-table-column>
          <!-- 插槽 头部插槽和内容插槽 -->
          <el-table-column
            v-else-if="item.type === 'slot'"
            :key="configString + index + 1"
            v-bind="item"
            :show-overflow-tooltip="item.tooltip === false ? false : true"
          >
            <template #header>
              <slot
                v-if="item.headerSlotName"
                :name="item.headerSlotName"
                v-bind="{ row: item }"
              ></slot>
              <template v-else>{{ item.label }}</template>
            </template>
            <!-- 内容的插槽 -->
            <template #default="scope">
              <slot
                :name="item.slotName || item.name"
                v-bind="{ value: scope.row[item.prop], row: scope.row }"
              ></slot>
            </template>
          </el-table-column>
          <!-- 纯内容 -->
          <el-table-column
            v-else
            :key="configString + index + 2"
            v-bind="item"
            :show-overflow-tooltip="item.tooltip === false ? false : true"
          >
            <template #header>
              <slot
                v-if="item.headerSlotName"
                :name="item.headerSlotName"
                v-bind="{ row: item }"
              ></slot>
              <template v-else>{{ item.label }}</template>
            </template>
            <!-- 有两级的情况使用children -->
            <template v-if="item.children">
              <el-table-column
                v-for="(item, key) in item.children"
                :key="key"
                v-bind="item"
                :show-overflow-tooltip="item.tooltip === false ? false : true"
              >
                <template #default="scope">
                  <slot
                    v-if="item.type === 'slot'"
                    :name="item.slotName || item.name"
                    v-bind="{ row: scope.row }"
                  ></slot>
                  <table-cell v-else :item="item" :scope="scope" @handlerEvent="handlerEvent" />
                </template>
              </el-table-column>
            </template>
            <!-- 没有children -->
            <template v-if="!item.children" #default="scope">
              <table-cell :item="item" :scope="scope" @handlerEvent="handlerEvent" />
            </template>
          </el-table-column>
        </template>
      </template>
    </el-table>
    <div v-if="paging && paging.total / paging.size > 1" class="shim"></div>
    <div
      v-if="paging && paging.total / paging.size > 1 && paging.type"
      class="pagination auto-pagination"
    >
      <div class="el-pagination is-background">
        <span class="el-pagination__jump is-first">
          <span class="el-pagination__goto">第</span>
          <div class="auto-width-box">
            <el-input
              class="el-input el-input--default el-pagination__editor is-in-pagination auto-width-input"
              size="large"
              :min="1"
              :max="totalPage"
              v-model="inputPage"
              :validate-event="false"
              @change="handleChange"
            ></el-input>
            <span class="occupy-span">{{ inputPage }}</span>
          </div>
          <span class="el-pagination__classifier">/{{ totalPage }}页</span>
        </span>
        <span class="el-pagination__total is-last">共 {{ paging.total }} 条</span>
      </div>
    </div>
    <div v-if="paging && paging.total / paging.size > 1 && !paging.type" class="pagination">
      <el-pagination
        v-if="paging.total / paging.size > 1"
        v-model:current-page="paging.page"
        :page-size="paging.size"
        :total="paging.total"
        :pager-count="paging.pagerCount || 7"
        :layout="paging.layout || 'total, prev, pager, next,jumper'"
        background
        @current-change="currentChange"
        v-bind="paging.attributes || {}"
      >
      </el-pagination>
    </div>
  </div>
</template>
<script setup>
import { ref, computed, onMounted, watch } from 'vue'
import TableCell from './Cell.vue'
import elementOffsetTop from './js/elementOffsetTop'
import debounce from './js/debounce'
const props = defineProps({
  config: {
    type: Array,
    default: () => []
  },
  data: {
    type: Array,
    default: () => []
  },
  paging: {
    type: Object,
    default: () => ({
      type: null,
      page: 1,
      size: 10,
      total: 0,
      layout: '',
      autoSize: false,
      tableHeader: null,
      offsetBottom: null
    })
  },
  loading: Boolean,
  tableClass: {
    // 自定义表格样式名称
    type: String,
    default: 'lsTable'
  },
  tableProps: Object, // 其他基于element-plus表格配置
  events: {
    type: Object,
    default: () => {}
  },
  lineHeight: {
    type: String,
    default: '50px'
  }
})
// 定义发送到父组件的事件
const emits = defineEmits([
  'handlePageChange', // 翻页
  'handleselection', // 选框改变
  'selectionChange', // 选框改变
  'sortChange', // 过滤改变
  'current-change' //翻页
])
let newTableProps = computed(() => {
  return JSON.stringify(props.tableProps)
})
watch(newTableProps, (val, oldVal) => {
  if (val && oldVal) {
    if (JSON.parse(val).height !== JSON.parse(oldVal).height) {
      autoTableContentByHeight()
    }
  }
})
const inputPage = ref(1)
watch(
  () => props.paging.page,
  (val, oldVal) => {
    if (val) {
      inputPage.value = val
    }
  },
  {
    deep: true,
    immediate: true
  }
)
let currentHeight = ref(document.body.clientHeight) // 当前高度
let selectedData = []
let sortData = {}
const propdata = null
const lsTable = ref(null) // 组件引用
const configString = computed(() => {
  // 可优化 JSON.stringify(props.config)
  return 1
})
// 方法
// 处理点击表格当前项目按钮事件
const handlerEvent = (event, row, currItemKey, scope) => {
  emits(event, row, currItemKey, scope)
}
// 翻页
const handlePageChange = (val) => {
  emits('handlePageChange', val, propdata)
}
const currentChange = (val) => {
  emits('current-change', val)
}
// 当选择项发生变化时会触发该事件
const handleSelectionChange = (val) => {
  selectedData = val
  emits('handleselection', val)
  emits('selectionChange', val)
}
// 过滤改变事件
const sortChange = (val) => {
  sortData = val
  emits('sortChange', val)
}
// 设置表格一页最大行数
const autoTableContentHeight = (type) => {
  if (!lsTable.value) return
  if (type !== 'init' && window.innerHeight === currentHeight.value) return
  const el = lsTable.value.$el // 表格dom节点
  const tableHeader = props.paging.tableHeader || parseFloat(props.lineHeight) // 头部高度
  const offsetTop = elementOffsetTop(el) // table距离顶部的高度
  const fullHeight = document.body.clientHeight
  currentHeight.value = fullHeight
  const offsetBottom = props.paging.offsetBottom || 82 // 距离底部的高度 分页高度32
  const tableLineHeight = parseFloat(props.lineHeight) //行高
  const visibleHeight = fullHeight - offsetTop - tableHeader - offsetBottom // 计算内容高度
  const rows = Math.floor(visibleHeight / tableLineHeight)
  const oldPages = Math.ceil(props.paging.total / props.paging.size)
  const nowPages = Math.ceil(props.paging.total / rows)
  if (oldPages > nowPages && props.paging.page > nowPages) {
    props.paging.page = nowPages
  }
  props.paging.size = rows < 1 ? 1 : rows
  emits('current-change', props.paging.page)
}
const autoTableContentByHeight = () => {
  if (!lsTable.value) return
  const tableLineHeight = parseFloat(props.lineHeight) //行高
  const tableHeader = props.paging.tableHeader || parseFloat(props.lineHeight) // 头部高度
  const visibleHeight = props.tableProps.height - tableHeader
  const rows = Math.floor(visibleHeight / tableLineHeight)
  const oldPages = Math.ceil(props.paging.total / props.paging.size)
  const nowPages = Math.ceil(props.paging.total / rows)
  if (oldPages > nowPages && props.paging.page > nowPages) {
    props.paging.page = nowPages
  }
  props.paging.size = rows < 1 ? 1 : rows
  emits('current-change', props.paging.page)
}
// 初始化
onMounted(() => {
  if (props.paging.autoSize) {
    autoTableContentHeight('init')
    window.addEventListener('resize', debounce(autoTableContentHeight, 1000))
  }
})
defineExpose({
  lsTable
})
// 新分页
const totalPage = computed(() => Math.ceil(props.paging.total / props.paging.size))
const handleChange = (val) => {
  const value = val ? ((+val || 1) < 1 ? 1 : +val || 1) : 1
  props.paging.page =
    value > Math.ceil(props.paging.total / props.paging.size)
      ? Math.ceil(props.paging.total / props.paging.size)
      : value
  inputPage.value = props.paging.page
  emits('current-change', props.paging.page)
}
</script>
<style scoped>
.table-container > :deep(.el-table tr) {
  height: v-bind(lineHeight) !important;
  /* line-height: v-bind(lineHeight) !important; */
}
.auto-width-box {
  width: auto;
  position: relative;
  padding: 0 10px;
  min-width: 56px;
}
.auto-width-input {
  width: 100%;
  position: absolute;
  left: 0;
  top: 50%;
  transform: translate(0, -50%);
}
.occupy-span {
  position: relative;
  left: 0;
  opacity: 0;
  padding: 0 10px;
  min-width: 56px;
  pointer-events: none;
}
.auto-pagination {
  height: 40px;
}
</style>
